package com.bangcommunity.bbframe.springredis.mq.task;

import com.bangcommunity.bbframe.springredis.mq.processor.AbstractProcessor;
import com.bangcommunity.bbframe.springredis.mq.processor.Processors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import java.util.ArrayList;
import java.util.List;

public abstract class AbstractTask<T> implements Runnable,ApplicationContextAware {
    protected final Logger logger = LoggerFactory.getLogger(this.getClass());
    protected T data;
    private ApplicationContext applicationContext;

    @Override
    public void run() {
        T data = getData();
        logger.debug("start " + this.getClass() + " do task data={}", data);
        try {
            ApplicationContext context = getApplicationContext();
            if (null == context) {
                logger.error("no springcontext for task {}", this.getClass());
                return;
            }
            processWork(data);
        } catch (Exception e) {
            logger.debug("end " + this.getClass() + " do task exception data={},error={}", data, e.getMessage());
            return;
        }
        logger.debug("end " + this.getClass() + " do task data={}", data);
    }

    public void processWork(T data) {
        List<Class<? extends AbstractProcessor>> processorList = getProcessor();
        for (Class<? extends AbstractProcessor> processorClass : processorList) {
            AbstractProcessor processor = null;
            try {
                processor = getApplicationContext().getBean(processorClass);
                logger.debug("start processor process : task={},processor={},data={},error={}", this.getClass(),
                        processor.getClass(), data);
                processor.process(data);
                logger.debug("end processor process : task={},processor={},data={},error={}", this.getClass(),
                        processor.getClass(), data);
            } catch (Exception e) {
                logger.error("end processor process error: task={},processor={},data={},error={}", this.getClass(),
                        processor.getClass(), data, e.getMessage());
            }
        }
    }

    public T getData() {
        return this.data;
    }

    public void setData(T data) {
        this.data = data;
    }

    private List<Class<? extends AbstractProcessor>> getProcessor() {
        Processors processors = this.getClass().getAnnotation(Processors.class);
        Class[] classes = processors.value();
        List<Class<? extends AbstractProcessor>> taskList = new ArrayList<>();
        for (Class task : classes) {
            taskList.add(task);
        }
        return taskList;
    }
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
    public ApplicationContext getApplicationContext(){
        return this.applicationContext;
    }

}
